package com.wnxy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wnxy.dto.OrderDto;
import com.wnxy.dto.OrderValidateDto;
import com.wnxy.dto.StatusCode;
import com.wnxy.exception.LoginException;
import com.wnxy.exception.OrderException;
import com.wnxy.model.Order;
import com.wnxy.mapper.OrderMapper;
import com.wnxy.model.Perform;
import com.wnxy.model.Ticket;
import com.wnxy.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wnxy.service.PerformService;
import com.wnxy.service.TicketService;
import com.wnxy.util.BeanCopyUtil;
import com.wnxy.util.CommonsUtil;
import com.wnxy.util.DateUtil;
import com.wnxy.util.GetRequestUtil;
import com.wnxy.vo.OrderValideVo;
import com.wnxy.vo.OrderVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author alice
 * @since 2021-10-25
 */
@Transactional
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    private PerformService performService;
    @Autowired
    private TicketService ticketService;
    @Autowired
    private StringRedisTemplate srt;
    @Autowired
    private RedisTemplate<String, Object> rt;

    @Override
    public OrderValidateDto sendCode(OrderValideVo orderValideVo) throws IllegalAccessException {
        System.out.println(orderValideVo);
        if (!CommonsUtil.hasAllFields(orderValideVo)) throw new OrderException(StatusCode.ORDERERROR.getCode(), "请填写完整信息");
//      1.判断表演是否存在
        Perform perform = performService.getOne(new QueryWrapper<Perform>().eq("perform_id", orderValideVo.getPerformId()));
        if (null == perform) throw new OrderException(StatusCode.ORDERERROR.getCode(), "演出信息不存在");
        if (perform.getPerformStatus()!=1) throw new OrderException(StatusCode.ORDERERROR.getCode(), "演出信息不存在");
        List<Integer> ticketIds = orderValideVo.getTicketIds();
        if (null == ticketIds) throw new OrderException(StatusCode.ORDERERROR.getCode(), "请选择座位");
        String regTel = "^1[3-9]\\d{9}$";
        String phone = orderValideVo.getOrderTel();
        if (!Pattern.matches(regTel, phone)) throw new OrderException(StatusCode.ORDERERROR.getCode(), "请输入可用手机号");
        //<==============================>
        String s = srt.opsForValue().get("wnxy:theater:user:" + phone);
        Long time = srt.opsForValue().getOperations().getExpire("wnxy:theater:user:" + phone);
        if (null!=s) throw new LoginException(StatusCode.LOGINERROR.getCode(), "验证码已发送,"+time+"秒后重置");
        String code = CommonsUtil.getCode(6);
        srt.opsForValue().set("wnxy:theater:user:"+phone,code,60, TimeUnit.SECONDS);
        OrderValidateDto orderValidateDto = BeanCopyUtil.copyProperties(orderValideVo, OrderValidateDto.class);
        orderValidateDto.setCode(code);
        return orderValidateDto;
    }
    //生成订单
    @Override
    public OrderDto createOrder() throws IllegalAccessException {
        HttpServletRequest request = GetRequestUtil.getRequest();
        String code = request.getParameter("code");
        String orderTel = request.getParameter("orderTel");
        String performId = request.getParameter("performId");
        String[] ticketIds = request.getParameterValues("ticketIds");
//      1.判断表演是否存在
        Perform perform = performService.getOne(new QueryWrapper<Perform>().eq("perform_id", Integer.valueOf(performId)));
        if (null == perform) throw new OrderException(StatusCode.ORDERERROR.getCode(), "演出信息不存在");
        if (perform.getPerformStatus()!=1) throw new OrderException(StatusCode.ORDERERROR.getCode(), "演出信息不存在");
        if (null == ticketIds) throw new OrderException(StatusCode.ORDERERROR.getCode(), "请选择座位");
        String regTel = "^1[3-9]\\d{9}$";
        String phone = orderTel;
        if (!Pattern.matches(regTel, phone)) throw new OrderException(StatusCode.ORDERERROR.getCode(), "请输入可用手机号");
        //<==============查看票务是否被选择================>
//        rt.opsForHash().values("wnxy:theater:order:"+order.getOrderId())



        //<==============================>
        Object o = rt.opsForValue().get("wnxy:theater:user:" + phone);
        System.out.println(o);
        System.out.println(code);
        if(o==null||!code.equals(o.toString())) throw new OrderException(StatusCode.ORDERERROR.getCode(), "验证码错误");
        Order order = new Order();
        order.setOrderPerformId(perform.getPerformId());
        order.setOrderNo(CommonsUtil.getOrderNo());//订单编号
        order.setOrderCode(CommonsUtil.getCode(6));//取票码
        order.setOrderTel(phone);//订单手机号
        //查redis票务数据
        List<Object> ticketIds1 = Arrays.asList(ticketIds);
        List<Object> list = rt.opsForHash().multiGet("wnxy:theater:ticket:"+performId, ticketIds1);
        List<Ticket> tickets = BeanCopyUtil.copyList(list, Ticket.class);
        Double total=0.0;
        for (Ticket ticket : tickets) {
            total+=ticket.getTicketPrice();
        }
        order.setOrderTotal(total);
        order.setOrderTime(DateUtil.parseDateLong(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss"));
        System.out.println(order);
        save(order);//保存订单
        for (Ticket ticket : tickets) {
            //绑定订单ID到票上面
            ticket.setTicketOrderId(order.getOrderId());
            ticket.setTicketStatus(1);
            rt.opsForValue().set("pwnxy:theater:order"+order.getOrderId(),order.getOrderPerformId()+"",60,TimeUnit.MINUTES);
            rt.opsForHash().put("wnxy:theater:order:"+order.getOrderId(),ticket.getTicketId()+"",ticket);
            rt.opsForHash().put("wnxy:theater:ticket:"+order.getOrderPerformId(),ticket.getTicketId()+"",ticket);
        }
        rt.opsForHash().getOperations().expire("wnxy:theater:order:"+order.getOrderId(),30, TimeUnit.MINUTES);
        return BeanCopyUtil.copyProperties(order, OrderDto.class);
    }

    @Override
    public void finish(String out_trade_no) {
        //修改订单状态
        Order order = getOne(new QueryWrapper<Order>().eq("order_no", out_trade_no));
        order.setOrderStatus(1);
        updateById(order);
        //票据存入数据库
        List<Object> values = rt.opsForHash().values("wnxy:theater:order:" + order.getOrderId());
        List<Ticket> tickets = BeanCopyUtil.copyList(values, Ticket.class);
        tickets.forEach(ticket -> {
            rt.opsForHash().delete("wnxy:theater:order:"+order.getOrderTel(),ticket.getTicketId()+"");
            ticket.setTicketId(null);
            ticket.setTicketStatus(2);
        });
        System.out.println(tickets);
        ticketService.saveBatch(tickets);

    }

    @Override
    public  void failure(String out_trade_no) {
        //修改订单状态
        Order order = this.getOne(new QueryWrapper<Order>().eq("order_no", out_trade_no));
        order.setOrderStatus(0);
        updateById(order);
        //票据存入数据库
        List<Object> values = rt.opsForHash().values("wnxy:theater:order:" + order.getOrderId());
        List<Ticket> tickets = BeanCopyUtil.copyList(values, Ticket.class);
        for (Ticket ticket : tickets) {
            //绑定订单ID到票上面
            ticket.setTicketOrderId(order.getOrderId());
            ticket.setTicketStatus(0);
            rt.opsForHash().put("wnxy:theater:ticket:"+order.getOrderPerformId(),ticket.getTicketId()+"",ticket);
        }
    }
}
